<?php
namespace addons\fastworker\library\command;

use GatewayWorker\BusinessWorker;
use GatewayWorker\Gateway;
use GatewayWorker\Register;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use Workerman\Worker;

/**
 * Worker 命令行类
 */
class GatewayWorker extends Command
{
    protected $config;

    public function configure()
    {
        $this->setName('fastworker:gateway')
            ->addArgument('action', Argument::OPTIONAL, "start|stop|restart|reload|status|connections", 'start')
            ->addOption('host', null, Option::VALUE_OPTIONAL, 'the host of GatewayWorker.', null)
            ->addOption('port', null, Option::VALUE_OPTIONAL, 'the port of GatewayWorker.', null)
            ->addOption('name', null, Option::VALUE_OPTIONAL, 'the name of GatewayWorker instance.', null)
            ->addOption('count', null, Option::VALUE_OPTIONAL, 'the number of GatewayWorker processes', null)
            ->addOption('protocol', null, Option::VALUE_OPTIONAL, 'the protocol of GatewayWorker', null)
            ->addOption('rhost', null, Option::VALUE_OPTIONAL, 'the register host of GatewayWorker', null)
            ->addOption('rport', null, Option::VALUE_OPTIONAL, 'the register port of GatewayWorker', null)
            ->addOption('lanip', null, Option::VALUE_OPTIONAL, 'the lanIp of GatewayWorker', null)
            ->addOption('gport', null, Option::VALUE_OPTIONAL, 'the startPort of GatewayWorker', null)
            ->addOption('pil', null, Option::VALUE_OPTIONAL, 'the pingInterval of GatewayWorker', null)
            ->addOption('pnrl', null, Option::VALUE_OPTIONAL, 'the pingNotResponseLimit of GatewayWorker', null)
            ->addOption('bname', null, Option::VALUE_OPTIONAL, 'the name of BusinessWorker', null)
            ->addOption('bcount', null, Option::VALUE_OPTIONAL, 'the number of of BusinessWorker processes', null)
            ->addOption('event', null, Option::VALUE_OPTIONAL, 'the eventHandler of BusinessWorker', null)
            ->addOption('deploy', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'Distributed Deployment', null)
            ->addOption('daemon', null, Option::VALUE_NONE, 'Run the workerman server in daemon mode.')
            ->addOption('initiative', null, Option::VALUE_NONE, 'Heartbeat initiative mode.')
            ->setDescription('Fastworker Gateway : Run GatewayWorker');

    }

    public function execute(Input $input, Output $output)
    {
        $action = $input->getArgument('action');

        if (DIRECTORY_SEPARATOR !== '\\') {
            if (!in_array($action, ['start', 'stop', 'reload', 'restart', 'status', 'connections'])) {
                $output->writeln("<error>Invalid argument action:{$action}, Expected start|stop|restart|reload|status|connections .</error>");
                return false;
            }

            global $argv;
            array_shift($argv);
            array_shift($argv);
            array_unshift($argv, 'think', $action);
        } elseif ('start' != $action) {
            $output->writeln("<error>Not Support action:{$action} on Windows.</error>");
            return false;
        }

        if ('start' == $action) {
            $output->writeln('Starting GatewayWorker server...');
        }

        $this->config = [

            'context'               => [],

            // Register配置

            'registerAddress'       => $this->getOption('rhost','127.0.0.1').':'.$this->getOption('rport','1236'),


            // Gateway配置
            'protocol'              => $this->getOption('protocol','websocket'),
            'host'                  => $this->getOption('host','127.0.0.1'),
            'port'                  => $this->getOption('port','2345'),
            'name'                  => $this->getOption('name','fastworker'),
            'count'                 => $this->getOption('count',1),
            'lanIp'                 => $this->getOption('lanip','127.0.0.1'),
            'startPort'             => $this->getOption('gport',2000),
            'daemonize'             => $this->input->hasOption('daemon') ? true : false,
            'pingInterval'          => $this->getOption('pil',30),
            'pingNotResponseLimit'  => $this->getOption('pnrl',0),
            'pingData'              => $this->input->hasOption('initiative') ? '{"type":"ping"}' : '',


            // BusinsessWorker配置
            'businessWorker'        => [
                'name'         => $this->getOption('bname','BusinessWorker'),
                'count'        => $this->getOption('bcount',1),
                'eventHandler' => $this->getOption('event','addons\\fastworker\\example\\GatewayWorker'),
            ],

        ];


        if ($this->getDeployOption('register')) {
            // 分布式部署的时候其它服务器可以关闭register服务
            // 注意需要设置不同的lanIp
            $this->register();
        }

        // 启动businessWorker
        if ($this->getDeployOption('business')) {
            $this->businessWorker();
        }

        // 启动gateway
        if ($this->getDeployOption('gateway')) {
            $this->gateway();
        }

        Worker::runAll();
    }

    /**
     * 启动register
     * @access public
     * @return void
     */
    public function register()
    {
        // 初始化register
        new Register('text://' . $this->config['registerAddress']);
    }


    public function businessWorker()
    {
        // 初始化 bussinessWorker 进程
        $worker = new BusinessWorker();
        foreach ($this->config['businessWorker'] as $k => $v){
            $worker->$k = $v;
        }
        $worker->registerAddress = $this->config['registerAddress'];
    }


    public function gateway()
    {
        // 初始化 gateway 进程

        $socket   = $this->config['protocol'] . '://' . $this->config['host'] . ':' . $this->config['port'];
        unset($this->config['host'], $this->config['port'], $this->config['protocol']);
        $gateway = new Gateway($socket, $this->config['context']);
        unset($this->config['context']);
        unset($this->config['businessWorker']);
        // 属性设置
        foreach ($this->config as $name => $val) {
            if (in_array($name, ['stdoutFile', 'daemonize', 'pidFile', 'logFile'])) {
                Worker::${$name} = $val;
                unset($this->config[$name]);
            }else{
                $gateway->$name = $val;
            }
        }
    }

    protected function getOption($name,$default){
        if ($this->input->hasOption($name)) {
            return $this->input->getOption($name);
        }
        return $default;
    }

    protected function getDeployOption($name){
        if ($this->input->hasOption('deploy')) {
            $deployList =  $this->input->getOption('deploy');
            return in_array($name,$deployList) ? true : false;
        }
        return true;  //默认全部
    }



}
